package org.hsc.proxy;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetSocketAddress;
import java.net.SocketException;

/**
 * The proxy server mediator.
 * @author Alon Halfon
 */
public class ProxyServerMediator extends ReliableUDPClient {
	
    /** the proxy server this mediator manage  */
    private HttpProxyServer proxyServer=null;
    
    /**contain the current max file size of the proxy the mediator manage */
    private int proxyCacheSize;
    
    /*
     * Holds the time to live value for each host handler.
     */
    private int ttl;
    
    ProxyServerMediator(int port, int cacheSize, int ttl) throws SocketException{
        super(port, -1);//timeout is still unknown
        this.proxyCacheSize=cacheSize;
        this.ttl = ttl;
    }
    
    ProxyServerMediator(int port,InetSocketAddress address, int cacheSize, int ttl) throws SocketException{
        super(port, address);//not in use?
        this.proxyCacheSize=cacheSize;
        this.ttl = ttl;
    }

    /**
     * get the message from the server
     * and process it.
     */
    private String processMessage(String messageWithID) throws IOException, Exception{
        String returnMessage=null;
        String message=messageWithID.split("@ID@",2)[0];
        //the first word is the method
        int currentID=Integer.parseInt(messageWithID.split("@ID@",2)[1]);
        String method=message.split(" ",2)[0];
        //more than one word commands
        //the KEEP ALIVE method have two words...
        if (method.equals("KEEP"))
            method=method+" "+message.split(" ",2)[1];
        
        if (method.equals("NUM"))//NUM OF PIPE CONNECTIONS
            method=method+" "+message.split(" ",5)[1]+" "+message.split(" ",5)[2]+" "+message.split(" ",5)[3];
        if (method.equals("START"))//START CACHE
            if (message.split(" ",3)[1].equals("CACHE"))//if it's not "CACHE" it's could be just start.
                method=method+" CACHE";
        if (method.equals("STOP"))//STOP CACHE
            if (message.split(" ",3)[1].equals("CACHE"))//if it's not "CACHE" it's could be just start.
                method=method+" CACHE";
        if (method.equals("CACHE"))//CACHE SIZE
            method=method+" "+message.split(" ",3)[1];
        if (method.equals("CLEAR"))//CLEAR CACHE
            method=method+" "+message.split(" ",3)[1];
       
        
        if (method.equals("START"))
        {
            //start running the server
            int httpPort=Integer.parseInt(message.split(" ",2)[1]);
            if (proxyServer==null)
                 proxyServer = new HttpProxyServer(httpPort,this.proxyCacheSize, ttl);
            if (proxyServer.getIsListening())
                returnMessage= "START ERROR: ALREADY RUNNING";
            else
            {
                try
                {
                    proxyServer.start();
                    returnMessage= "START OK";
                }
                catch(IOException ioe)
                {
                    returnMessage = "START ERROR: UNAVAILABLE PORT";
                }
            }
        } else if (method.equals("CLIENTS"))
        {
            if (proxyServer==null)
            {
                returnMessage= "CLIENTS ERROR: NOT ALIVE";
            }
            else
                returnMessage= proxyServer.getIsListening()?
                    "CLIENTS "+String.valueOf(proxyServer.getClientsCount()):"CLIENTS ERROR: NOT ALIVE";
                
            //GENEREATE RESPONSE BY THE SERVER STATUS
            //THIS IS ONLY FOR DEBUGGING
        } else if (method.equals("KEEP ALIVE"))
        {
            //GENEREATE RESPONSE BY THE SERVER STATUS
            //THIS IS ONLY FOR DEBUGGING
            if (proxyServer==null)
                returnMessage= "KEEP ALIVE ERROR: NOT ALIVE";
            else
                returnMessage= proxyServer.getIsListening()?
                    "KEEP ALIVE OK":
                    "KEEP ALIVE ERROR: NOT ALIVE";
        }else if (method.equals("CLOSE"))
        {
            if (proxyServer!=null)
            {
                if (proxyServer.getIsListening())
                {
                    proxyServer.stop();
                    proxyServer=null;
                    
                    returnMessage= "CLOSE OK";
                }
                else
                    returnMessage= "CLOSE ERROR: NOT ALIVE";
            }
            else
                returnMessage= "CLOSE ERROR: NOT ALIVE";
             
        } else if (method.equals("EXIT"))
        {
            if (proxyServer!=null)
                 proxyServer.stop();
            returnMessage= "EXIT OK"; 
        }else if(method.equals("START CACHE"))
        {
            if (proxyServer==null)
                returnMessage= "START CACHE ERROR: NOT ALIVE";
            else
            {
                if (proxyServer.getIsListening())
                {
                    this.proxyServer.getCache().turnOn();
                    returnMessage="START CACHE OK";
                }
                else
                    returnMessage="START CACHE ERROR: NOT ALIVE";
            }
                    
                    
        }else if (method.equals("STOP CACHE"))
        {
            if (proxyServer==null)
                returnMessage= "STOP CACHE ERROR: NOT ALIVE";
            else
            {
                if (proxyServer.getIsListening())
                {
                    this.proxyServer.getCache().turnOff();
                    returnMessage="STOP CACHE OK";
                }
                else
                    returnMessage="START CACHE ERROR: NOT ALIVE";
            }
                
        }else if (method.equals("NUM OF PIPE CONNECTIONS"))
        {//TODO
            
        }else if (method.equals("CACHE SIZE"))
        {
            
            if (proxyServer==null)
                returnMessage= "CACHE SIZE ERROR: NOT ALIVE";
            else
            {
                if (proxyServer.getIsListening())
                {
                    int newCacheSize=Integer.parseInt(message.split(" ",3)[2]);//change size if server is down?
                    this.proxyServer.getCache().setMaxCacheSize(newCacheSize);
                    returnMessage="CACHE SIZE UPDATED TO "+Integer.toString(newCacheSize);
                }
                else
                    returnMessage="CACHE SIZE ERROR: NOT ALIVE";
            }
                
        }else if (method.equals("CLEAR CACHE"))
        {
            if (proxyServer==null)
                returnMessage= "CLEAR CACHE ERROR: NOT ALIVE";
            else
            {
                if (proxyServer.getIsListening())
                {
                    this.proxyServer.getCache().clearCache();
                    returnMessage="CLEAR CACHE OK";
                }
                else
                    returnMessage="CLEAR CACHE ERROR: NOT ALIVE";
            }
        }else if (method.equals("MAX"))
        {
            if (proxyServer==null)
                returnMessage= "MAX ERROR: NOT ALIVE";
            else
            {
                if (proxyServer.getIsListening())
                {
                    int newMax=Integer.parseInt(message.split(" ",2)[1]);
                    this.proxyServer.setMaxFileSize(newMax);
                    returnMessage="MAX OK";
                }
                else
                    returnMessage="MAX ERROR: NOT ALIVE";
            }
            
        }else{
            returnMessage= "error";// if the message was damaged while it was sent
        }
        return returnMessage+"@ID@"+String.valueOf(currentID);
    }

    /*
     * function read from manager
     * and exectue the operations
     * untill EXIT message
     */
    public void start() throws IOException, TimedOutException, Exception{
        String response="";
        while (!response.split("@ID@")[0].equals("EXIT OK"))
        {
            DatagramPacket packet= this.recive();
            
            String received = new String(packet.getData(),0,packet.getLength());
            
            response=processMessage(received);
        //    if (response.split("@ID@",2)[0].equals("START OK"))
       //     {//first interaction - setting up manager's ip
                
                address=new InetSocketAddress(packet.getAddress(), packet.getPort());
                port=packet.getPort();
       //     }
            sendNoResponse(response);
        }
    }   
    
}